﻿using System;
using System.Linq;
using System.Data.SqlClient;
using System.Collections.Generic;

using LeanEngine.Entity;
using LeanEngine.Extensions;

namespace LeanEngine.Data.SqlClient
{
    internal sealed class SqlClientDataCommand : IDataCommand, IDisposable
    {
        #region Declaration Members

        private SqlCommand command;

        #endregion

        #region Constructor Members

        public SqlClientDataCommand()
        {
            command = new SqlCommand();
        }

        #endregion

        #region IDataCommand Members

        public void ExecuteBulkInsert<T>(IList<T> elementsList) 
            where T : PlainEntity
        {
            using (var bcp = new SqlClientBulkInsertCommand())
            {
                bcp.Execute<T>(command.Connection, command.Transaction, elementsList, 0);
            }
        }

        public void ExecuteBulkInsert<T>(IList<T> elementsList, int timeOut) 
            where T : PlainEntity
        {
            using (var bcp = new SqlClientBulkInsertCommand())
            {
                bcp.Execute<T>(command.Connection, command.Transaction, elementsList, timeOut);
            }
        }

        public global::System.Data.Common.DbParameter NewParameter(string name, object value)
        {
            if (!name.StartsWith("@"))
            {
                name = "@" + name;
            }

            if (value.IsNull())
            {
                value = DBNull.Value;
            }

            return new SqlParameter(name, value);
        }

        public int ExecuteNonQuery()
        {
            return command.ExecuteNonQuery();
        }

        public global::System.Data.IDataReader ExecuteReader(global::System.Data.CommandBehavior behavior)
        {
            return command.ExecuteReader(behavior);
        }

        public global::System.Data.IDataReader ExecuteReader()
        {
            return command.ExecuteReader();
        }
        
        public object ExecuteScalar()
        {
            return command.ExecuteScalar();
        }

        public global::System.Data.Common.DbParameterCollection Parameters
        {
            get { return command.Parameters; }
        }

        public string CommandText
        {
            get { return command.CommandText; }
            set { command.CommandText = value; }
        }

        public global::System.Data.CommandType CommandType
        {
            get { return command.CommandType; }
            set { command.CommandType = value; }
        }

        public int CommandTimeout
        {
            get { return command.CommandTimeout; }
            set { command.CommandTimeout = value; }
        }

        public global::System.Data.Common.DbConnection Connection
        {
            get { return command.Connection; }
            set { command.Connection = (SqlConnection)value; }
        }

        public global::System.Data.Common.DbTransaction Transaction
        {
            get { return command.Transaction; }
            set { command.Transaction = (SqlTransaction)value; }
        }

        #endregion

        #region IDisposable Members

        /// <summary>
        /// Release all resources used
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Release all resources used
        /// </summary>
        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.command != null)
                {
                    if (this.command.Transaction == null &&
                        this.command.Connection != null)
                    {
                        this.command.Connection.Close();
                        this.command.Connection.Dispose();
                        this.command.Connection = null;
                    }

                    this.Parameters.Clear();
                    this.command = null;
                }
            }
        }

        #endregion
    }
}
